/***************************************************************
*  Copyright (c) 2007 by GroupMe! Team (www.groupme.net)
*  All rights reserved.
*
*  This file is part of the GroupMe! Project. Source code of 
*  this project is closed and redistribution of this code is
*  prohibited. 
*  
*  Contact: http://www.groupme.net
*
*  This copyright notice MUST APPEAR in all copies of the file!
***************************************************************/
package net.groupme.logging.utils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.GregorianCalendar;

import org.springframework.jdbc.object.SqlUpdate;

import net.groupme.gui.constants.VIEW_VOCABULARY;
import net.groupme.model.ObjectFactory;
import net.groupme.model.dao.DATABASE_CONSTANTS;


/**
 * created on Oct 12, 2007
 * 
 * This class parses the Server-Access-Log-File and tranforms it into 
 * a format that can be imported into GroupMe! database.
 * 
 * @author Patrick Siehndel
 * @author Fabian Abel
 * @author last edited by: $Author: fabian $
 * 
 * @version $Revision: 1.3 $ $Date: 2008-01-09 19:13:57 $
 */
public class AccessLogMatcher {

	public static void main(String[] arguments) {
		parsingMethodUsingAccessFileAsMainSource();
		
	}
	
	public static void parsingMethodUsingAccessFileAsMainSource(){
		String logFileVonProliant = new String(	"/home/fabian/krams/GroupMe/logs/groupme_access_2008-01-04.log");
		FileWriter fw = null;
		try {
			fw = new FileWriter(new File("/home/fabian/krams/GroupMe/logs/cleaned-logs.csv"));
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		//wollte nur mal testen, ob man inner methode ne klasse anlegen kann...
		class LogEvent {
			public String ipAddress = null;
			public String keyword = null;
			public String resourceId = null;
			public String timestamp = null;
			public String toString(){
				return ipAddress + (keyword == null ? (" clicked on " + resourceId) : (" searched for " +  keyword)) + " - " + timestamp;
			}
			public String toCSVString(){
				if(keyword == null){
					return ";NULL;'" + ipAddress + "';'resourceclick';NULL;'" + resourceId +"';'" + timestamp + "'";
				}else{
					return ";NULL;'" + ipAddress + "';'tagsearch';'" + keyword + "';NULL;'" + timestamp + "'";
				}
			}
		}
		int numberOfBrowseGroupMenuClicks = 0;
		try {
			LogEvent actualLog = null;
			String month = null;
			FileReader serverLogFileReader = new FileReader(logFileVonProliant);
			BufferedReader serverLogReader = new BufferedReader(serverLogFileReader);
			String actualLine = serverLogReader.readLine();
			String year = "";
			while (actualLine != null) {
				if(actualLine.contains(VIEW_VOCABULARY.ACTION_BROWSE_GROUPS + " ")){
					numberOfBrowseGroupMenuClicks++;
				}
				if(actualLine.contains(VIEW_VOCABULARY.ACTION_SEARCH) || 
						actualLine.contains(VIEW_VOCABULARY.ACTION_BROWSE_GROUPS) || 
						actualLine.contains(VIEW_VOCABULARY.ACTION_VIEW_RESOURCE)){
					actualLog = new LogEvent();
					
					//ipAddress:
					actualLog.ipAddress = actualLine.substring(0, actualLine.indexOf(" - -"));
					actualLine = actualLine.substring(actualLine.indexOf("[")+1);
					
					//timestamp:
					
					if(actualLine.contains("/2007:")){
						month = actualLine.substring(2, actualLine.indexOf("/2007:"));
						year = "2007";
					}else if(actualLine.contains("/2008:")){
						month = actualLine.substring(2, actualLine.indexOf("/2008:"));
						year = "2008";
					}else if(actualLine.contains("/2009:")){
						month = actualLine.substring(2, actualLine.indexOf("/2009:"));
						year = "2009";
					}
					month = month.replaceAll("/Jul", "07").replaceAll("/Aug", "08").replaceAll("/Sep", "09").replaceAll("/Oct", "10").replaceAll("/Nov", "11").replaceAll("/Dec", "12").replaceAll("/Jan", "01");//.replaceAll("/Feb", "02").replaceAll("/Mar", "03").replaceAll("/Apr", "04");
					actualLog.timestamp = year + "-" + month + "-" + actualLine.substring(0, 2) + " " + actualLine.substring(actualLine.indexOf("/" + year + ":") + 6, actualLine.indexOf(" +"));
					
					actualLine = actualLine.substring(actualLine.indexOf("\"GET /") + 6);
					if(actualLine.contains(VIEW_VOCABULARY.ACTION_SEARCH) && actualLine.contains("?keyword=") && !actualLine.contains("searchfor=")){
						actualLog.keyword = actualLine.substring(actualLine.indexOf("?keyword=") + 9, actualLine.indexOf(" HTTP/"));
						actualLog.keyword = actualLog.keyword.replaceAll("%22", "\"").replaceAll("%20", " ").replaceAll("%C3%BC", "ü").replaceAll("%C3%A4", "ä").replaceAll("%FC", "ü").replaceAll("%C2%B4", "´").replaceAll("%C3%B6", "ö");
					}else if(actualLine.contains("id=")){
						actualLog.resourceId = actualLine.substring(actualLine.indexOf("?id=") + 4, actualLine.indexOf(" HTTP/"));
					}
					if(actualLog.keyword != null || actualLog.resourceId != null){
						try{
						//	performDBUpdate(actualLog.ipAddress, actualLog.keyword, actualLog.resourceId, Timestamp.valueOf(actualLog.timestamp));
						}catch(Exception e){
							e.printStackTrace();
						}
						System.out.println(actualLog);
						fw.write(actualLog.toCSVString() + "\n");
					}
				}
				
				//read next line:
				actualLine = serverLogReader.readLine();
			}
			fw.flush();
			fw.close();
		}catch(IOException e){
			e.printStackTrace();
		}
		System.out.println("numberOfBrowseGroupMenuClicks: " + numberOfBrowseGroupMenuClicks);
	}
	
	private static long offset = 20000;
	
	public static void performDBUpdate(String ip, String keyword, String resourceID, Timestamp timeStamp){
		String query = null;
		timeStamp.setTime(timeStamp.getTime() - offset);
		String from = timeStamp.toString();
		from = from.substring(0, from.lastIndexOf("."));
		timeStamp.setTime(timeStamp.getTime() + offset + offset);
		String to = timeStamp.toString();
		to = to.substring(0, to.lastIndexOf("."));
		if(keyword != null){
			query = "UPDATE " + DATABASE_CONSTANTS.TABLE_LOG_EVENT_NAVIGATION + " SET " + DATABASE_CONSTANTS.LOG_EVENT_NAVIGATION_SESSION_ID + " = '" + ip + "'  " +
					" WHERE " + DATABASE_CONSTANTS.LOG_EVENT_NAVIGATION_SEARCH_STRING + " = '" + keyword + "' AND " +
							DATABASE_CONSTANTS.LOG_EVENT_NAVIGATION_TIMESTAMP + " > '" + from + "' AND " + 
							DATABASE_CONSTANTS.LOG_EVENT_NAVIGATION_TIMESTAMP + " < '" + to + "'"; 
		}else if(resourceID != null){
			query = "UPDATE " + DATABASE_CONSTANTS.TABLE_LOG_EVENT_NAVIGATION + " SET " + DATABASE_CONSTANTS.LOG_EVENT_NAVIGATION_SESSION_ID + " = '" + ip + "'  " +
			" WHERE " + DATABASE_CONSTANTS.LOG_EVENT_NAVIGATION_RESOURCE_ID + " = '" + resourceID + "' AND " +
					DATABASE_CONSTANTS.LOG_EVENT_NAVIGATION_TIMESTAMP + " > '" + from + "' AND " + 
					DATABASE_CONSTANTS.LOG_EVENT_NAVIGATION_TIMESTAMP + " < '" + to + "'"; 
		}else{
			System.out.println("Panik!");
		}
		SqlUpdate su = new SqlUpdate(ObjectFactory.ds, query);
		su.compile();
		su.update();
		
	}
	
	public static void parsingMethodA(){
		String logFileVonProliant = new String(
				//"c:/Users/patrick/Desktop/groupme_access2.log");
				"/home/fabian/krams/GroupMe/logs/groupme_access_2007-10-12.log");
		// DIE Datei welche in der DB von Groupme ist als DOS CVS mit " um die
		// Werte und ; als Trenner
		String logFileVonGroupme = new String(
				//"c:/Users/patrick/Desktop/Logvongroupme.txt");
				"/home/fabian/krams/GroupMe/logs/LogEventNavigation.txt");
		int maxOffset = 2000;
		
		
		//Die Datei in die die neue Datei für die DB geschrieben wird
		String filename = "/home/fabian/krams/GroupMe/logs/LogEventNavigationForImport.txt";
		
		try {
			FileReader log1 = new FileReader(logFileVonProliant);
			BufferedReader log1reader = new BufferedReader(log1);
			String ipAdress = new String();
			String date = new String();
			String date2 = new String();
			boolean eof = false;
			int log1Length = 0;
			while (!eof) {
				if (log1reader.readLine() == null) {
					eof = true;
				} else {
					log1Length++;
				}
			}
			String[][] log1array = new String[log1Length][2];
			FileReader log2 = new FileReader(logFileVonProliant);
			BufferedReader log1reader2 = new BufferedReader(log2);
			int firstMinus = 0;
			int actualPos = 0;
			eof = false;
			while (!eof) {
				String line = log1reader2.readLine();
				if (line == null) {
					eof = true;
				} else {
					firstMinus = line.indexOf("-");
					ipAdress = line.substring(0, firstMinus - 1);
					date = line.substring(firstMinus + 5, firstMinus + 25);

					log1array[actualPos][0] = ipAdress;

					date = date.replace("Oct", "10");
					date = date.replace("Sep", "09");
					date = date.replace("Nov", "11");

					date2 = date.substring(6, 10) + "-" + date.substring(3, 5)
							+ "-" + date.substring(0, 2) + " "
							+ date.substring(11, 19);

					log1array[actualPos][1] = date2;

					actualPos++;

				}
			}
			log1reader.close();
			log1.close();
			log1reader2.close();
			log2.close();

			int i = 0;
			while (i < log1Length) {
				// System.out.println(log1array[i][0]+ " " + log1array[i][1]);
				i++;
			}
			// System.out.println(log1Length);

			FileReader log3 = new FileReader(logFileVonGroupme);
			BufferedReader log3reader = new BufferedReader(log3);

			boolean eof3 = false;
			int log3Length = 0;
			while (!eof3) {
				if (log3reader.readLine() == null) {
					eof3 = true;
				} else {
					log3Length++;
				}
			}
			String[][] log2array = new String[log3Length][7];

			FileReader log4 = new FileReader(logFileVonGroupme);
			BufferedReader log4reader = new BufferedReader(log4);
			String groupmeID = new String();
			String groupmeUSERID = new String();
			String groupmeSESSIONID = new String();
			String groupmeACTION = new String();
			String groupmeVALUE = new String();
			String groupmeRESOURCEID = new String();
			String groupmeTIMEANDDATE = new String();

			int actualPos2 = 0;
			int firstSemi = 0;
			int secondSemi = 0;
			int thirdSemi = 0;
			int fourthSemi = 0;
			int fifthSemi = 0;
			int sixthSemi = 0;

			eof = false;
			while (!eof) {
				String line = log4reader.readLine();
				if (line == null) {
					eof = true;
				} else {

					firstSemi = line.indexOf(";") + 1;
					secondSemi = line.substring(firstSemi).indexOf(";")
							+ firstSemi + 1;
					thirdSemi = line.substring(secondSemi).indexOf(";")
							+ secondSemi + 1;
					fourthSemi = line.substring(thirdSemi).indexOf(";")
							+ thirdSemi + 1;
					fifthSemi = line.substring(fourthSemi).indexOf(";")
							+ fourthSemi + 1;
					sixthSemi = line.substring(fifthSemi).indexOf(";")
							+ fifthSemi + 1;

					groupmeID = line.substring(0, firstSemi).trim();
					groupmeUSERID = line.substring(firstSemi, secondSemi);
					groupmeSESSIONID = line.substring(secondSemi, thirdSemi);
					groupmeACTION = line.substring(thirdSemi, fourthSemi);
					groupmeVALUE = line.substring(fourthSemi, fifthSemi);
					groupmeRESOURCEID = line.substring(fifthSemi, sixthSemi);
					groupmeTIMEANDDATE = line.substring(sixthSemi);

					// System.out.println(groupmeID + " - - " + groupmeUSERID +
					// " - - " + groupmeSESSIONID + " - - " +groupmeACTION + " -
					// - " +groupmeVALUE + " - - " +groupmeRESOURCEID + " - - "
					// + groupmeTIMEANDDATE);

					log2array[actualPos2][0] = groupmeID;
					log2array[actualPos2][1] = groupmeUSERID;
					log2array[actualPos2][2] = groupmeSESSIONID;
					log2array[actualPos2][3] = groupmeACTION;
					log2array[actualPos2][4] = groupmeVALUE;
					log2array[actualPos2][5] = groupmeRESOURCEID;
					log2array[actualPos2][6] = groupmeTIMEANDDATE;

					actualPos2++;
				}
			}

			int runner1 = 0;
			int runner2 = 30000;
			int treffer = 0;
			int offsetTreffer = 0;
			int runtreffer = 30000;

			GregorianCalendar Date1 = new GregorianCalendar();
			GregorianCalendar Date2 = new GregorianCalendar();
			boolean offSetProp = false;
			while (runner1 < log3Length) {
				runner2 = runtreffer;
				 System.out.println(runner1);
				// System.out.println(runner2);
				String dateStr1 = new String(log2array[runner1][6]);

				System.out.println(dateStr1);
		if(dateStr1.length() > 0){//begin hack-if
				int year = Integer.valueOf(dateStr1.substring(1, 5));
				int month = Integer.valueOf(dateStr1.substring(6, 8));
				int day = Integer.valueOf(dateStr1.substring(9, 11));
				int hour = Integer.valueOf(dateStr1.substring(12, 14));
				int minute = Integer.valueOf(dateStr1.substring(15, 17));
				int second = Integer.valueOf(dateStr1.substring(18, 20));
				Date1.set(year, month, day, hour, minute, second);

				String dateStr2 = ("\"" + log1array[runner2][1] + "\"");

				year = Integer.valueOf(dateStr2.substring(1, 5));
				month = Integer.valueOf(dateStr2.substring(6, 8));
				day = Integer.valueOf(dateStr2.substring(9, 11));
				hour = Integer.valueOf(dateStr2.substring(12, 14));
				minute = Integer.valueOf(dateStr2.substring(15, 17));
				second = Integer.valueOf(dateStr2.substring(18, 20));
				Date2.set(year, month, day, hour, minute, second);

				while (runner2 < log1Length) {
					dateStr2 = ("\"" + log1array[runner2][1] + "\"");
					year = Integer.valueOf(dateStr2.substring(1, 5));
					month = Integer.valueOf(dateStr2.substring(6, 8));
					day = Integer.valueOf(dateStr2.substring(9, 11));
					hour = Integer.valueOf(dateStr2.substring(12, 14));
					minute = Integer.valueOf(dateStr2.substring(15, 17));
					second = Integer.valueOf(dateStr2.substring(18, 20));
					Date2.set(year, month, day, hour, minute, second);

					if (Date1.equals(Date2)) {
						log2array[runner1][2]= "\""+log1array[runner2][0]+"\";";
						
						
						
						treffer++;
						runtreffer = runner2;
						runner2 = log1Length;

					}
					if (offSetProp == true) {
						if (Date2.getTimeInMillis() - Date1.getTimeInMillis() <= maxOffset) {
							log2array[runner1][2]= "\""+log1array[runner2][0]+"\";";
							runner2 = log1Length;
// System.out.println("OFFSETPROBELMSOLVED");
							offsetTreffer++;

						}

						offSetProp = false;
					}

					if (Date2.after(Date1)) {
// System.out.println("ALARM OFFSET");
// System.out.println(runner2);
// System.out.println(runner1);
						if (Date2.getTimeInMillis() - Date1.getTimeInMillis() <= maxOffset) {
							log2array[runner1][2]= "\""+log1array[runner2][0]+"\";";
							runner2 = log1Length;
							offsetTreffer++;
						} else {
							offSetProp = true;
							runner2 = runner2 - 2;
						}

						// System.out.println(Date2.getTimeInMillis()-Date1.getTimeInMillis());
						// System.out.println("Offset Treffer: "+ dateStr1 + " "
						// + dateStr2);
					}

					runner2++;

				}

				runner1++;

			}else{
				runner1++;
			}//ende hack-if-else
			}
			

			System.out.println("Treffer: " + treffer);
			System.out.println("Treffer mit Offset unter " + (maxOffset / 1000)
					+ " sek : " + offsetTreffer);
			System.out.println("Gesamt: " + (treffer + offsetTreffer));
			
			
			File ausgabe = new File(filename);
			FileWriter fw = new FileWriter(ausgabe);
			BufferedWriter out = new BufferedWriter(fw);
			i = 0;
			while (i < log3Length){
				System.out.println();
				out.write(log2array[i][0]+log2array[i][1]+log2array[i][2]+log2array[i][3]+log2array[i][4]+log2array[i][5]+log2array[i][6]);
				out.newLine();
				i++;
			}
			
			out.close();
			fw.close();
			
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
